﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace WPFSample.ChooseFontSample
{
    class FontDialog : Window
    {
        TextBoxWithLister boxFamily, boxStyle, boxWeight, boxStretch, boxSize;
        Label lblDisplay;
        bool isUpdateSuppressed = true;

        public Typeface Typeface
        {
            set
            {
                if (this.boxFamily.Contains(value.FontFamily))
                {
                    this.boxFamily.SelectedItem = value.FontFamily;
                }
                else
                {
                    this.boxFamily.SelectedIndex = 0;
                }

                if (this.boxStyle.Contains(value.Style))
                {
                    this.boxStyle.SelectedItem = value.Style;
                }
                else
                {
                    this.boxStyle.SelectedIndex = 0;
                }

                if (this.boxWeight.Contains(value.Weight))
                {
                    this.boxWeight.SelectedItem = value.Weight;
                }
                else
                {
                    this.boxWeight.SelectedIndex = 0;
                }

                if (this.boxStretch.Contains(value.Stretch))
                {
                    this.boxStretch.SelectedItem = value.Stretch;
                }
                else
                {
                    this.boxStretch.SelectedIndex = 0;
                }
            }

            get
            {
                return new Typeface((FontFamily)this.boxFamily.SelectedItem,
                    (FontStyle)this.boxStyle.SelectedItem,
                    (FontWeight)this.boxWeight.SelectedItem,
                    (FontStretch)this.boxStretch.SelectedItem);
            }
        }

        public double FaceSize
        {
            set
            {
                double size = 0.75 * value;
                this.boxSize.Text = size.ToString();
                if (!this.boxSize.Contains(size))
                {
                    this.boxSize.Insert(0, size);
                }

                this.boxSize.SelectedItem = size;
            }

            get
            {
                double size;
                if (!double.TryParse(this.boxSize.Text, out size))
                {
                    size = 8.25;
                }

                return size / 0.75;
            }
        }

        public FontDialog()
        {
            this.Title = "Font";
            this.ShowInTaskbar = false;
            this.WindowStyle = WindowStyle.ToolWindow;
            this.WindowStartupLocation = WindowStartupLocation.CenterOwner;
            this.SizeToContent = SizeToContent.WidthAndHeight;
            this.ResizeMode = ResizeMode.NoResize;

            Grid gridMain = new Grid();
            this.Content = gridMain;

            RowDefinition rowdef = new RowDefinition();
            rowdef.Height = new GridLength(200, GridUnitType.Pixel);
            gridMain.RowDefinitions.Add(rowdef);

            rowdef = new RowDefinition();
            rowdef.Height = new GridLength(150, GridUnitType.Pixel);
            gridMain.RowDefinitions.Add(rowdef);

            rowdef = new RowDefinition();
            rowdef.Height = GridLength.Auto;
            gridMain.RowDefinitions.Add(rowdef);

            ColumnDefinition coldef = new ColumnDefinition();
            coldef.Width = new GridLength(650, GridUnitType.Pixel);
            gridMain.ColumnDefinitions.Add(coldef);

            Grid gridBoxes = new Grid();
            gridMain.Children.Add(gridBoxes);

            rowdef = new RowDefinition()
            {
                Height = GridLength.Auto
            };
            gridBoxes.RowDefinitions.Add(rowdef);

            rowdef = new RowDefinition()
            {
                Height = new GridLength(100, GridUnitType.Star)
            };
            gridBoxes.RowDefinitions.Add(rowdef);

            coldef = new ColumnDefinition()
            {
                Width = new GridLength(175, GridUnitType.Star)
            };
            gridBoxes.ColumnDefinitions.Add(coldef);

            coldef = new ColumnDefinition()
            {
                Width = new GridLength(100, GridUnitType.Star)
            };
            gridBoxes.ColumnDefinitions.Add(coldef);

            coldef = new ColumnDefinition()
            {
                Width = new GridLength(100, GridUnitType.Star)
            };
            gridBoxes.ColumnDefinitions.Add(coldef);

            coldef = new ColumnDefinition()
            {
                Width = new GridLength(100, GridUnitType.Star)
            };
            gridBoxes.ColumnDefinitions.Add(coldef);

            coldef = new ColumnDefinition()
            {
                Width = new GridLength(75, GridUnitType.Star)
            };
            gridBoxes.ColumnDefinitions.Add(coldef);

            Label lbl = new Label()
            {
                Content = "Font Family",
                Margin = new Thickness(12, 12, 12, 0)
            };
            gridBoxes.Children.Add(lbl);
            Grid.SetRow(lbl, 0);
            Grid.SetColumn(lbl, 0);

            this.boxFamily = new TextBoxWithLister()
            {
                IsReadOnly = true,
                Margin = new Thickness(12, 0, 12, 12)
            };
            gridBoxes.Children.Add(this.boxFamily);
            Grid.SetRow(this.boxFamily, 1);
            Grid.SetColumn(this.boxFamily, 0);

            lbl = new Label()
            {
                Content = "Style",
                Margin = new Thickness(12, 12, 12, 0)
            };
            gridBoxes.Children.Add(lbl);
            Grid.SetRow(lbl, 0);
            Grid.SetColumn(lbl, 1);

            this.boxStyle = new TextBoxWithLister()
            {
                IsReadOnly = true,
                Margin = new Thickness(12, 0, 12, 12)
            };
            gridBoxes.Children.Add(this.boxStyle);
            Grid.SetRow(this.boxStyle, 1);
            Grid.SetColumn(this.boxStyle, 1);

            lbl = new Label()
            {
                Content = "Weight",
                Margin = new Thickness(12, 12, 12, 0)
            };
            gridBoxes.Children.Add(lbl);
            Grid.SetRow(lbl, 0);
            Grid.SetColumn(lbl, 2);

            this.boxWeight = new TextBoxWithLister()
            {
                IsReadOnly = true,
                Margin = new Thickness(12, 0, 12, 12)
            };
            gridBoxes.Children.Add(this.boxWeight);
            Grid.SetRow(this.boxWeight, 1);
            Grid.SetColumn(this.boxWeight, 2);

            lbl = new Label()
            {
                Content = "Stretch",
                Margin = new Thickness(12, 12, 12, 0)
            };
            gridBoxes.Children.Add(lbl);
            Grid.SetRow(lbl, 0);
            Grid.SetColumn(lbl, 3);

            this.boxStretch = new TextBoxWithLister()
            {
                IsReadOnly = true,
                Margin = new Thickness(12, 0, 12, 12)
            };
            gridBoxes.Children.Add(this.boxStretch);
            Grid.SetRow(this.boxStretch, 1);
            Grid.SetColumn(this.boxStretch, 3);

            lbl = new Label()
            {
                Content = "Size",
                Margin = new Thickness(12, 12, 12, 0)
            };
            gridBoxes.Children.Add(lbl);
            Grid.SetRow(lbl, 0);
            Grid.SetColumn(lbl, 4);

            this.boxSize = new TextBoxWithLister()
            {
                IsReadOnly = true,
                Margin = new Thickness(12, 0, 12, 12)
            };
            gridBoxes.Children.Add(this.boxSize);
            Grid.SetRow(this.boxSize, 1);
            Grid.SetColumn(this.boxSize, 4);

            this.lblDisplay = new Label()
            {
                Content = "AaBbCc XxYyZz 012345",
                HorizontalContentAlignment = HorizontalAlignment.Center,
                VerticalContentAlignment = VerticalAlignment.Center
            };
            gridMain.Children.Add(this.lblDisplay);
            Grid.SetRow(this.lblDisplay, 1);

            Grid gridButtons = new Grid();
            gridMain.Children.Add(gridButtons);
            Grid.SetRow(gridButtons, 2);

            for (int i = 0; i < 5; i++)
            {
                gridButtons.ColumnDefinitions.Add(new ColumnDefinition());
            }

            Button btn = new Button()
            {
                Content = "OK",
                IsDefault = true,
                HorizontalAlignment = HorizontalAlignment.Center,
                MinWidth = 60,
                Margin = new Thickness(12)
            };
            btn.Click += this.OkOnClick;
            gridButtons.Children.Add(btn);
            Grid.SetColumn(btn, 1);

            btn = new Button()
            {
                Content = "Cancel",
                IsCancel = true,
                HorizontalAlignment = HorizontalAlignment.Center,
                Margin = new Thickness(12),
                MinWidth = 60
            };
            gridButtons.Children.Add(btn);
            Grid.SetColumn(btn, 3);

            foreach (FontFamily fam in Fonts.SystemFontFamilies)
            {
                this.boxFamily.Add(fam);
            }

            double[] ptsizes = new double[] { 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72 };
            foreach (double ptsize in ptsizes)
            {
                this.boxSize.Add(ptsize);
            }

            this.boxFamily.SelectionChanged += this.FamilyOnSelectionChanged;
            this.boxStyle.SelectionChanged += this.StyleOnSelectionChanged;
            this.boxWeight.SelectionChanged += this.StyleOnSelectionChanged;
            this.boxStretch.SelectionChanged += this.StyleOnSelectionChanged;
            this.boxSize.TextChanged += this.SizeOnTextChanged;

            Typeface = new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch);
            this.FaceSize = this.FontSize;
            this.boxFamily.Focus();
            this.isUpdateSuppressed = false;
            this.UpdateSample();
        }

        private void UpdateSample()
        {
            if (this.isUpdateSuppressed)
            {
                return;
            }

            this.lblDisplay.FontFamily = (FontFamily)this.boxFamily.SelectedItem;
            this.lblDisplay.FontStyle = (FontStyle)this.boxStyle.SelectedItem;
            this.lblDisplay.FontWeight = (FontWeight)this.boxWeight.SelectedItem;
            this.lblDisplay.FontStretch = (FontStretch)this.boxStretch.SelectedItem;

            double size;
            if (!double.TryParse(this.boxSize.Text, out size))
            {
                size = 8.25;
            }

            this.lblDisplay.FontSize = size / 0.75;
        }

        private void SizeOnTextChanged(object sender, TextChangedEventArgs e)
        {
            this.UpdateSample();
        }

        private void StyleOnSelectionChanged(object sender, EventArgs e)
        {
            this.UpdateSample();
        }

        private void FamilyOnSelectionChanged(object sender, EventArgs e)
        {
            FontFamily fntfam = (FontFamily)this.boxFamily.SelectedItem;

            FontStyle? fntstyPrevious = (FontStyle?)this.boxStyle.SelectedItem;
            FontWeight? fntwtPrevious = (FontWeight?)this.boxWeight.SelectedItem;
            FontStretch? fntstrPrevious = (FontStretch?)this.boxStretch.SelectedItem;

            this.isUpdateSuppressed = true;

            this.boxStyle.Clear();
            this.boxWeight.Clear();
            this.boxStretch.Clear();

            foreach (FamilyTypeface ftf in fntfam.FamilyTypefaces)
            {
                if (!this.boxStyle.Contains(ftf.Style))
                {
                    if (ftf.Style == FontStyles.Normal)
                    {
                        this.boxStyle.Insert(0, ftf.Style);
                    }
                    else
                    {
                        this.boxStyle.Add(ftf.Style);
                    }
                }

                if (!this.boxWeight.Contains(ftf.Weight))
                {
                    if (ftf.Weight == FontWeights.Normal)
                    {
                        this.boxWeight.Insert(0, ftf.Weight);
                    }
                    else
                    {
                        this.boxWeight.Add(ftf.Weight);
                    }
                }

                if (!this.boxStretch.Contains(ftf.Stretch))
                {
                    if (ftf.Stretch == FontStretches.Normal)
                    {
                        this.boxStretch.Insert(0, ftf.Stretch);
                    }
                    else
                    {
                        this.boxStretch.Add(ftf.Stretch);
                    }
                }
            }

            if (this.boxStyle.Contains(fntstyPrevious))
            {
                this.boxStyle.SelectedItem = fntstyPrevious;
            }
            else
            {
                this.boxStyle.SelectedIndex = 0;
            }

            if (this.boxWeight.Contains(fntwtPrevious))
            {
                this.boxWeight.SelectedItem = fntwtPrevious;
            }
            else
            {
                this.boxWeight.SelectedIndex = 0;
            }

            if (this.boxStretch.Contains(fntstrPrevious))
            {
                this.boxStretch.SelectedItem = fntstrPrevious;
            }
            else
            {
                this.boxStretch.SelectedIndex = 0;
            }

            this.isUpdateSuppressed = false;
            this.UpdateSample();
        }

        private void OkOnClick(object sender, RoutedEventArgs e)
        {
            this.DialogResult = true;
        }
    }
}
